package com.xishu.controller;

import com.xishu.bo.RowAndColumn;
import com.xishu.config.Constant;
import com.xishu.entity.shop.FoodTableConfig;
import com.xishu.response.ResponseData;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.CommonService;
import com.xishu.service.FoodTableService;
import com.xishu.service.RunModelService;
import com.xishu.service.ShopService;
import com.xishu.util.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.stream.Collectors;

import static com.xishu.response.ResponseStatus.FOOD_TABLE_SAME;

/**
 * 餐桌的配置
 */
@RestController
@Api(description = "餐桌配置")
public class FoodTableConfigController implements Tools {
    private static Logger logger = LoggerFactory.getLogger(FoodTableConfigController.class);
    private FoodTableService foodTableService = FoodTableService.getInstance();
    private CommonService commonService = CommonService.getInstance();
    private ShopService shopService = ShopService.getInstance();
    private RunModelService runModelService = RunModelService.getInstance();

    @ApiOperation(value = "查询餐桌设置")
    @PutMapping(value = ("/user/food/table/config"), produces = ("application/json;charset=UTF-8"))
    public ResponseData list(@RequestBody FoodTableConfig foodTableConfig) throws Exception {
        return commonService.searchResponse(foodTableConfig);
    }

    @ApiOperation(value = "删除餐桌设置")
    @DeleteMapping(value = ("/user/food/table/config"), produces = ("application/json;charset=UTF-8"))
    public ResponseData delete(@RequestBody FoodTableConfig foodTableConfig) throws Exception {
        return commonService.delete(foodTableConfig);
    }

    @ApiOperation(value = "创建餐桌配置")
    @PostMapping(value = ("/user/food/table/config"), produces = ("application/json;charset=UTF-8"))
    public ResponseData create(@RequestBody FoodTableConfig foodTableConfig) throws Exception {
        VerifyUtil.verify(() -> isNotEmpty(foodTableConfig.getShopId()));
        updateFoodTableConfigSort(foodTableConfig);

        Long shopId = foodTableConfig.getShopId();
        //添加索引
        List<FoodTableConfig> tableConfigList = ShopService.getInstance().findFoodTableConfig(shopId);
        OptionalInt optionalInt = tableConfigList.stream().mapToInt(p -> getInt(p.getShowIndex())).max();
        if (optionalInt.isPresent()) {
            foodTableConfig.setShowIndex(optionalInt.getAsInt() + 1);
        } else {
            //如果没有，从1开始
            foodTableConfig.setShowIndex(1);
        }

        //判断是否已经存在了这些前綴+號碼
        //List<FoodTableConfig> foodTableConfigList = ShopService.getInstance().findFoodTableConfig(foodTableConfig.getShopId());
        //List<RowAndColumn> allRowAndColumnList = foodTableConfigList.stream().flatMap(p -> getList(p.getRowAndColumnList()).stream()).collect(Collectors.toList());
        //boolean isValid = isValidRowAndColumnList(allRowAndColumnList, foodTableConfig.getRowAndColumnList());
        //VerifyUtil.verify(() -> isValid, ResponseStatus.OTHER_FOOD_TABLE_CONFIG_CONFIG_IT);

        if (isNotEmpty(foodTableConfig.getRowAndColumnList()) && foodTableConfig.getMaxPerson() != null) {
            for (RowAndColumn rowAndColumn : foodTableConfig.getRowAndColumnList()) {
                rowAndColumn.setMaxPerson(foodTableConfig.getMaxPerson());
            }
        }

        return commonService.createObject(foodTableConfig);
    }

    @ApiOperation(value = "修改餐桌配置")
    @PutMapping(value = ("/user/food/table/config/modify"), produces = ("application/json;charset=UTF-8"))
    public ResponseData update(@RequestBody FoodTableConfig foodTableConfig) throws Exception {
        //新增或者创建的场景
        if (!getBoolean(foodTableConfig.getDeleteOperate())) {
            if (isNotEmpty(foodTableConfig.getRowAndColumnList())) {
                logger.info("will check row and column list");
                for (RowAndColumn rowAndColumn : foodTableConfig.getRowAndColumnList()) {
                    if (foodTableConfig.getMaxPerson() != null) {
                        rowAndColumn.setMaxPerson(foodTableConfig.getMaxPerson());
                    }
                }
            }

            updateFoodTableConfigSort(foodTableConfig);

            FoodTableConfig foodTableConfigInDb = commonService.findEntity(foodTableConfig.getId(), FoodTableConfig.class);
            //判断有没有相同的CODE，但是
            for (RowAndColumn rowAndColumn : foodTableConfig.getRowAndColumnList()) {
                List<RowAndColumn> rowAndColumnListInDb = getList(foodTableConfigInDb.getRowAndColumnList());
                if (isNotEmpty(rowAndColumnListInDb)) {
                    Optional<RowAndColumn> rowAndColumnOptional = rowAndColumnListInDb.stream().filter(p -> equals(p.getCode(), rowAndColumn.getCode())).findAny();
                    if (rowAndColumnOptional.isPresent()) {
                        VerifyUtil.verify(() -> rowAndColumnOptional.get().getRow().intValue() == rowAndColumn.getRow().intValue() && rowAndColumnOptional.get().getColumn().intValue() == rowAndColumn.getColumn().intValue(), FOOD_TABLE_SAME);
                    }
                }
            }

            return commonService.updateObject(foodTableConfig, (f) -> {
                //如果修改的时候，已经绑定了场景，那么对应场景的餐桌要一起修改
                try {
                    foodTableService.configToSceneFoodTable(f);
                } catch (Exception e) {
                    logger.error("e", e);
                }
            });
        } else {
            //删除的场景
            FoodTableConfig foodTableConfigInDb = commonService.findEntity(foodTableConfig.getId(), FoodTableConfig.class);
            List<RowAndColumn> reqRowAndColumnList = getList(foodTableConfig.getRowAndColumnList());
            List<RowAndColumn> rowAndColumnList = getList(foodTableConfigInDb.getRowAndColumnList());
            Iterator<RowAndColumn> iterator = rowAndColumnList.iterator();

            while (iterator.hasNext()) {
                RowAndColumn rowAndColumn = iterator.next();
                Optional<RowAndColumn> rowAndColumnOptional = foodTableService.findRowAndColumn(rowAndColumn, reqRowAndColumnList);
                if (rowAndColumnOptional.isPresent()) {
                    iterator.remove();
                }
            }

            //从数据库里面清空之后，再写到请求里面
            foodTableConfig.setRowAndColumnList(rowAndColumnList);

            return commonService.updateObject(foodTableConfig, (f) -> {
                try {
                    foodTableService.configToSceneFoodTable(f);
                } catch (Exception e) {
                    logger.error("e", e);
                }
            });
        }
    }

    /**
     * 判断两个判断是否相等
     *
     * @param sceneList1
     * @param sceneList2
     * @return
     */
    private boolean isEquals(List<Long> sceneList1, List<Long> sceneList2) {
        if (isEmpty(sceneList1) && isEmpty(sceneList2)) {
            return true;
        }

        if (sceneList1.size() != sceneList2.size()) {
            return false;
        }

        for (Long sceneId : sceneList1) {
            if (!sceneList2.stream().filter(s -> s.longValue() == sceneId.longValue()).findAny().isPresent()) {
                return false;
            }
        }

        //全部都相等
        return true;
    }

    /**
     * 更新配置里面的横纵坐标
     *
     * @param foodTableConfig
     */
    private void updateFoodTableConfigSort(FoodTableConfig foodTableConfig) throws Exception {
        if (foodTableConfig.getArrangeSortType() == null) {
            logger.info("not the sort type");
            return;
        }

        VerifyUtil.verify(() -> foodTableConfig.getStartIndex() != null);
        VerifyUtil.verify(() -> isNotEmpty(foodTableConfig.getArrangeSortType()));
        VerifyUtil.verify(() -> foodTableConfig.getArrangeSortType().longValue() == Constant.SORT_ROW || foodTableConfig.getArrangeSortType().longValue() == Constant.SORT_COLUMN);

        //设置人数
        foodTableConfig.setMaxPerson(foodTableConfig.getMaxPerson());
        //排序
        foodTableService.sortFoodTable(foodTableConfig);

        //设置CODE
        List<RowAndColumn> rowAndColumnList = getList(foodTableConfig.getRowAndColumnList());

        for (int i = 0; i < rowAndColumnList.size(); i++) {
            RowAndColumn rowAndColumn = rowAndColumnList.get(i);
            rowAndColumn.setCode(getString(foodTableConfig.getCode()) + (foodTableConfig.getStartIndex() + i));
        }

        //创建，只需要更新横纵坐标就可以了
        if (foodTableConfig.getId() == null) {
            logger.info("create action");
            return;
        }

        logger.info("update action will merge row and column list");
        //如果存在ID，则查询后再更新,CODE
        FoodTableConfig foodTableConfigInDb = commonService.findEntity(foodTableConfig.getId(), FoodTableConfig.class);

        //依次查询，如果存在则更新
        for (RowAndColumn rowAndColumn : foodTableConfig.getRowAndColumnList()) {
            Optional<RowAndColumn> rowAndColumnOptionalInDB = foodTableConfigInDb.getRowAndColumnList().stream().filter(p -> getInt(p.getRow()) == getInt(rowAndColumn.getRow()) && getInt(p.getColumn()) == getInt(rowAndColumn.getColumn())).findAny();

            if (rowAndColumnOptionalInDB.isPresent()) {
                //设置新的CODE，如果客户端没有传CODE，那么就是1，2，3，4这样的
                rowAndColumnOptionalInDB.get().setCode(rowAndColumn.getCode());

                if (rowAndColumn.getMaxPerson() != null) {
                    rowAndColumnOptionalInDB.get().setMaxPerson(rowAndColumn.getMaxPerson());
                }
            } else {
                //不存在则添加
                foodTableConfigInDb.getRowAndColumnList().add(rowAndColumn);
            }
        }

        //最后将数据库里面的横纵坐标再设置成回来
        foodTableConfig.setRowAndColumnList(foodTableConfigInDb.getRowAndColumnList());
        logger.info("after merge result is {}", StringUtils.join(foodTableConfig.getRowAndColumnList(), ","));
    }

    /**
     * 检查其它的餐桌是否有相同的配置
     *
     * @param rowAndColumnListInDb
     * @param checkRowAndColumnList
     * @return
     */
    private boolean isValidRowAndColumnList(List<RowAndColumn> rowAndColumnListInDb, List<RowAndColumn> checkRowAndColumnList) {
        if (isEmpty(rowAndColumnListInDb)) {
            logger.info("otherRowAndColumnList is empty");
            return true;
        }

        for (RowAndColumn rowAndColumn : rowAndColumnListInDb) {
            Optional<RowAndColumn> rowAndColumnOptional = checkRowAndColumnList.stream().filter(p -> equals(p.getCode(), rowAndColumn.getCode())).findAny();

            if (rowAndColumnOptional.isPresent()) {
                logger.info("find the same code {}", rowAndColumn.getCode());
                return false;
            }
        }

        return true;
    }

}
